package com.fast.fast.common.satoken.config;

import cn.dev33.satoken.interceptor.SaRouteInterceptor;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

/**
 * Sa-Token配置类
 *
 * @author lyf
 * @date 2022/01/01 00:00 周六
 **/
@RequiredArgsConstructor
@ConditionalOnProperty(prefix = "sa-token", name = "open", havingValue = "true")
@EnableConfigurationProperties({SaTokenProperties.class})
@AutoConfiguration
public class SaTokenConfig implements WebMvcConfigurer {

    private final SaTokenProperties saTokenProperties;

    /**
     * 配置Sa-Token
     *
     * @return
     */
    @ConditionalOnProperty(prefix = "sa-token", name = "open", havingValue = "true")
    @Bean
    @Primary
    public cn.dev33.satoken.config.SaTokenConfig getSaTokenConfigPrimary() {
        return new cn.dev33.satoken.config.SaTokenConfig()
                // token名称(同时也是cookie名称)。默认值：satoken
                .setTokenName(saTokenProperties.getTokenName())
                // token有效期，单位：秒。默认值：2592000秒（30天）
                .setTimeout(saTokenProperties.getTimeout())
                // token临时有效期(指定时间内无操作就视为token过期)，单位：秒，-1表示永不过期。默认值：-1
                .setActivityTimeout(saTokenProperties.getActivityTimeout())
                // 是否允许同一账号并发登录(为true时允许并发登录，为false时新登录挤掉旧登录)。默认值：true
                .setIsConcurrent(saTokenProperties.getIsConcurrent())
                // 在多人登录同一账号时，是否共用一个token(为true时所有登录共用一个token，为false时每次登录新建一个token)。默认值：true
                .setIsShare(saTokenProperties.getIsShare())
                // token风格。默认值：uuid
                .setTokenStyle(saTokenProperties.getTokenStyle())
                // 是否输出操作日志。默认值：false
                .setIsLog(saTokenProperties.getIsLog());
    }

    /**
     * Sa-Token全局拦截器
     *
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册拦截器，自定义认证规则
        registry.addInterceptor(
                new SaRouteInterceptor((req, res, handler) -> {
                    // 权限认证--根据角色编码
                    List<String> roles = saTokenProperties.getRolesUrls().getRoles();
                    List<String> urls = saTokenProperties.getRolesUrls().getUrls();
                    if (ObjectUtil.isNotEmpty(roles) && ObjectUtil.isNotEmpty(urls)) {
                        SaRouter.match(urls).check(r -> StpUtil.checkRoleOr(ArrayUtil.toArray(roles, String.class)));
                    }

                    // 权限认证--根据权限编码
                    String perm = saTokenProperties.getPermsUrls().getPerm();
                    List<String> urls1 = saTokenProperties.getPermsUrls().getUrls();
                    if (ObjectUtil.isNotEmpty(perm) && ObjectUtil.isNotEmpty(urls1)) {
                        SaRouter.match(urls1).check(r -> StpUtil.checkPermission(perm));
                    }
                })
        ).addPathPatterns("/**");
    }
}
